/**
 * Computer Graphics Lecture WS 2009/2010 Ulm University
 * Creator: Manuel Finckh
 * Email:   manuel.finckh@uni-ulm.de
 */

#ifndef RENDER_H
#define RENDER_H

#include "bvh.h"
#include "rtStructs.h"
#include "utils/vec.h"
#include <math.h>
#include "utils/MersenneTwister.h"

#include "scene.h"
#include "cam.h"
#include "material.h"

#define SNAPX 320
#define SNAPY 240

class Render {
public:
    Scene *scene;
    Cam *cam;
    BVH *accel;

    MTRand *mtrand;
    int numThreads;

    Vec3 *image;
    Vec3 *actual;
    Vec3 *snapshot;
    int ResX, ResY;
    int sResX, sResY;
    int nResX, nResY;
    int accum_index;

    int depth;
    int nr_samples;

    int *accum_buffer;

    Render(Scene *scene);
    ~Render();

    float* render(int shader, int snap);

    inline Vec3 shade_debug(Ray &ray, HitRec &rec);
    inline Vec3 shade_simple(Ray &ray, HitRec &rec);
    inline Vec3 shade_mirror(Ray &ray, HitRec &rec);
    inline Vec3 shade_path(Ray &ray, HitRec &rec);
    inline Vec3 shade_pathDL(Ray &ray, HitRec &rec);
    inline Vec3 shade_path_iterative(Ray &ray, HitRec &rec);
    inline void light_trace(Ray &ray, HitRec &rec, Vec3 radiance);
    inline Vec3 shade_path_SSS(Ray &ray, HitRec &rec);
    inline void shrink_accum(float &inv_accum, float &shrink);
    inline Vec3 sample_hemisphere(Vec3 normal);
    inline float BRDF(Vec3 in, Vec3 out, Vec3 normal);
    inline float WardBRDF(Vec3 in, Vec3 out, Vec3 normal);
    inline void clearImage();
    inline Vec3 direct_illumination(Ray &ray, HitRec &rec);
    inline void accumulate(const int &x, const int &y, const Vec3 &color);
    inline float rand_exponential(const float &lambda);
    inline float schlick(const Vec3 &in, const Vec3 &n);
    inline Vec3 sample_sphere();
    inline void refract(Vec3 &out, const Vec3 &in, const Vec3 &n, float n0);
    inline void fresnel(float &R, float &T, const Vec3 &in, const Vec3 &n, float n1, float n2);
    inline float rad2deg(float rad);
    inline float dipole(Vec3 x0, Vec3 normal, Vec3 &x1, int &id);
    inline Vec3 direct_illumination(Vec3 & p, int &p_id);
};

#endif

